package tech.aistar.day13;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * 本类用来演示: 反射操作方法
 *
 * @author: success
 * @date: 2022/8/4 10:44 上午
 */
public class MethodDemo {
    public static void main(String[] args) {
        Point p = new Point();
        Class<?> c = p.getClass();

        //1. 获取所有的方法的Method - 私有的
        Method[] methods = c.getDeclaredMethods();

        //2. 反射获取方法的信息
        for (Method m : methods) {
            //System.out.println(m);

            //修饰符
            System.out.print(Modifier.toString(m.getModifiers())+" ");

            //返回类型 - 对象类型(最简称)
            System.out.print(m.getReturnType().getSimpleName()+" ");

            //方法的名称
            System.out.print(m.getName()+" (");

            //方法的参数列表 - 类型
            Class<?>[] parameterTypes = m.getParameterTypes();
            //防止是空参
            if(parameterTypes!=null && parameterTypes.length>0){
                for (int i = 0; i < parameterTypes.length; i++) {
                    System.out.print((i!=parameterTypes.length-1)?(parameterTypes[i].getSimpleName()+","):(parameterTypes[i].getSimpleName()));
                }
            }
            System.out.println(")");
        }

        System.out.println("===反射调用方法===");
        //1. 空参
        //根据指定的方法的名称来获取对应方法的Method实例
        try {
            Method m1 = c.getDeclaredMethod("test02");
            //反射调用该方法
            m1.invoke(p);//空参,第二个参数可以不传入

            //2. 一参
            Method m2 = c.getDeclaredMethod("test02",String.class);
            m2.invoke(p,"admin");

            //3. 两参
            Method m3 = c.getDeclaredMethod("test02",String.class,int.class);
            m3.invoke(p,"tom",20);

            //4. 一参,带有返回类型
            Method m4 = c.getDeclaredMethod("test",String.class);
            String result = (String) m4.invoke(p,"java");
            System.out.println(result);

            //5. 静态方法 - 不需要传入对象,第一个参数可以直接传入null
            Method m5 = c.getDeclaredMethod("test03",int.class);
            m5.invoke(null,100);

            //6. 反射可以破坏封装性,反射可以在外部调用私有的方法
            Method m6 = c.getDeclaredMethod("test04");
            //私有方法需要设置true - 可访问的
            m6.setAccessible(true);
            m6.invoke(p);

        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
